Imports GMap.NET
Imports GMap.NET.WindowsForms
Imports GMap.NET.WindowsForms.Markers
Imports System.Data.Common

''' <summary>
''' View stations locations using Google Maps control found at http://www.codeplex.com/gmap4dotnet
''' Note: change must be made to app.config file of program being compiles for GMap to work using .Net 4.0; see comments below
''' </summary>
Public Class frmGMap

    '  <!-- Must add useLegacyV2RuntimeActivationPolicy="true" below in order for the GMap control to work properly in .Net 4.0-->
    '  <startup useLegacyV2RuntimeActivationPolicy="true">
    '    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
    '  </startup>

    Private CenterPt As PointLatLng
    Private lyrStations As GMap.NET.WindowsForms.GMapOverlay

    Private Sub frmGMap_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        SaveWindowPos(REGAPP, Me)
        SaveSetting(REGAPP, Me.Name, "MapType", cboMapType.SelectedIndex)
        SaveSetting(REGAPP, Me.Name, "Zoom", trkZoom.Value)
    End Sub

    Private Sub frmGMap_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Try
            GetWindowPos(REGAPP, Me)
            With gMap
                .MarkersEnabled = True
                lyrStations = New GMap.NET.WindowsForms.GMapOverlay(gMap, "Stations")
                .Overlays.Add(lyrStations)
                .MouseWheelZoomType = MouseWheelZoomType.ViewCenter
                .DragButton = Windows.Forms.MouseButtons.Middle
                .IgnoreMarkerOnMouseWheel = True

                With cboMapType
                    .DropDownStyle = ComboBoxStyle.DropDownList
                    .MaxDropDownItems = 50
                    .Sorted = True
                    .Items.Clear()
                    'only add a subset of all available maps (too many!)
                    For Each mp As MapProviders.GMapProvider In MapProviders.GMapProviders.List
                        Dim s As String = mp.Name
                        If (s.ToUpper.StartsWith("ARCGIS") Or
                            s.ToUpper.StartsWith("BING") Or
                            s.ToUpper.StartsWith("GOOGLE") Or
                            s.ToUpper.StartsWith("OPENSTREET") Or
                            s.ToUpper.StartsWith("OVI") Or
                            s.ToUpper.StartsWith("YAHOO")) AndAlso
                            Not (s.ToUpper.Contains("CHINA") Or
                                 s.ToUpper.Contains("KOREA")) Then
                            .Items.Add(s.Replace("_", " "))
                        End If
                    Next
                    .SelectedIndex = GetSetting(REGAPP, Me.Name, "MapType", 0)
                End With

                If WRDBProject IsNot Nothing Then
                    With cboDisplay
                        .Items.Add("All Stations")
                        WRDBProject.ResetPDox("Stations")
                        .Items.AddRange(WRDBProject.DB.GetRecordList("Stations", "Station_Type").ToArray)
                        .SelectedIndex = 0
                        ReCenter()
                    End With
                End If

                trkZoom.Value = GetSetting(REGAPP, Me.Name, "Zoom", 7)
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub trkZoom_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles trkZoom.ValueChanged
        Try
            With gMap
                .Zoom = trkZoom.Value + .MinZoom
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub cboMapType_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboMapType.SelectedIndexChanged
        For Each mp As MapProviders.GMapProvider In MapProviders.GMapProviders.List
            If mp.Name = cboMapType.Text.Replace(" ", "_") Then
                gMap.MapProvider = mp
                Exit For
            End If
        Next
        gMap.Focus()
    End Sub

    Private Sub cboDisplay_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboDisplay.SelectedIndexChanged
        Try
            If WRDBProject Is Nothing Then Exit Sub

            Dim sumlat As Single = 0, sumlon As Single = 0, num As Integer = 0

            'MainForm.WriteProgress("Updating map...", ProgressBarStyle.Marquee)
            'gMap.ClearAllMarkers()
            lyrStations.Markers.Clear()

            Dim dr As DbDataReader = WRDBProject.DB.ExecuteReader("SELECT Station_ID,Station_Name,Latitude,Longitude FROM Stations" & IIf(cboDisplay.SelectedIndex = 0, "", " WHERE Station_Type='" & cboDisplay.Text & "'"))
            While dr IsNot Nothing And dr.Read
                Dim sta As String = TestNull(dr.GetValue(0), "")
                Dim nam As String = TestNull(dr.GetValue(1), "")
                Dim lat As Single = TestNull(dr.GetValue(2), 0)
                Dim lon As Single = -Math.Abs(TestNull(dr.GetValue(3), 0))
                If sta <> "" And Math.Abs(lat) > 0.5 And Math.Abs(lon) > 0.5 And Math.Abs(lat) < 90 And Math.Abs(lon) < 180 Then
                    sumlat += lat
                    sumlon += lon
                    num += 1
                    lyrStations.Markers.Add(New GMapMarkerStation(New PointLatLng(lat, lon), 0.7, sta & vbCrLf & nam))
                End If
                'If Not MainForm.WriteProgress("Preparing map...", ProgressBarStyle.Marquee) Then Exit While
            End While
            dr.Close()

            ' set initial map coordinates in Latitude,Longitude
            CenterPt = New PointLatLng(sumlat / num, sumlon / num)

            'MainForm.ProgressComplete()
            'gMap.ReloadMap()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub ReCenter()
        gMap.Position = CenterPt
    End Sub

    Private Sub LocatePlace()
        Try
            If txtLocation.Text = "" Then Exit Sub
            'first, try to find stationid
            With gMap
                If WRDBProject IsNot Nothing Then
                    Dim dr As DbDataReader = WRDBProject.DB.ExecuteReader("SELECT LATITUDE,LONGITUDE FROM STATIONS WHERE STATION_ID='{0}'", txtLocation.Text.ToUpper.Trim)
                    If dr IsNot Nothing AndAlso dr.Read Then
                        Dim lat As Single = TestNull(dr.GetValue(0), 0)
                        Dim lon As Single = -Math.Abs(TestNull(dr.GetValue(1), 0))
                        If lat < 1 Or lat > 90 Or Math.Abs(lon) < 1 Or Math.Abs(lon) > 180 Then
                            WarningMsg("Station ID {0} does not have valid values for latitude and longitude.", txtLocation.Text)
                        Else
                            .Position = New PointLatLng(lat, lon)
                            '.GoToCurrentPosition()
                        End If
                        dr.Close()
                        Exit Sub
                    End If
                End If

                If .SetCurrentPositionByKeywords(txtLocation.Text) Then
                    '.GoToCurrentPosition()
                Else
                    WarningMsg("That Station ID was not found and Google maps unable to find named place: " & txtLocation.Text)
                End If

            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            txtLocation.Text = ""
        End Try
    End Sub

    Private Sub btnLocation_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnLocation.Click
        LocatePlace()
    End Sub

    Private Sub frmGMap_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles Me.KeyPress
        If txtLocation.Focused And e.KeyChar = Chr(13) Then
            LocatePlace()
            e.Handled = True
        End If
    End Sub

    Private Sub gMap_OnMapZoomChanged() Handles gMap.OnMapZoomChanged
        With gMap
            trkZoom.Value = Math.Max(trkZoom.Minimum, Math.Min(trkZoom.Maximum, .Zoom - .MinZoom))
        End With
    End Sub

    'Private Sub gMap_OnCurrentPositionChanged(ByVal point As GMapNET.PointLatLng) Handles gMap.OnCurrentPositionChanged

    'End Sub

    Private Sub gMap_OnMarkerClick(ByVal item As GMap.NET.WindowsForms.GMapMarker, e As MouseEventArgs) Handles gMap.OnMarkerClick
        Try
            'Dim sta As String = item.Text.Split(vbCr)(0)
            Dim sta As String = item.ToolTipText.Split(vbCr)(0)
            Dim dr As DbDataReader = WRDBProject.DB.ExecuteReader("SELECT * FROM STATIONS WHERE STATION_ID='{0}'", sta)
            If dr IsNot Nothing And dr.Read Then
                Dim s As String = ""
                For i As Integer = 0 To dr.FieldCount - 1
                    s &= (dr.GetName(i) & ":").PadRight(15) & vbTab & TestNull(dr.GetValue(i), "") & vbCr
                Next
                MessageBox.Show(s, "Station Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
            End If
            dr.Close()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Public Sub New(ByVal _WRDBProject As WRDB.Project.clsProject)

        ' This call is required by the Windows Form Designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        WRDBProject = _WRDBProject
    End Sub

    Private Sub ToolStripButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton1.Click
        VB6.WhatsThisMode(Me)
    End Sub

    Private Sub picPanUp_Click(sender As System.Object, e As System.EventArgs) Handles picPanUp.Click
        With gMap
            .Position = New PointLatLng(.Position.Lat + .CurrentViewArea.HeightLat / 2, .Position.Lng)
        End With
    End Sub

    Private Sub picPanLt_Click(sender As System.Object, e As System.EventArgs) Handles picPanLt.Click
        With gMap
            .Position = New PointLatLng(.Position.Lat, .Position.Lng - .CurrentViewArea.WidthLng / 2)
        End With
    End Sub

    Private Sub picPanRt_Click(sender As System.Object, e As System.EventArgs) Handles PictureBox1.Click, picPanRt.Click
        With gMap
            .Position = New PointLatLng(.Position.Lat, .Position.Lng + .CurrentViewArea.WidthLng / 2)
        End With
    End Sub

    Private Sub picPanDn_Click(sender As System.Object, e As System.EventArgs) Handles picPanDn.Click
        With gMap
            .Position = New PointLatLng(.Position.Lat - .CurrentViewArea.HeightLat / 2, .Position.Lng)
        End With
    End Sub
End Class

Public Class GMapMarkerStation
    Inherits GMapMarker

    Private pen As Pen
    Private _ScaleFactor As Single

    Public Sub New(ByVal p As PointLatLng, ByVal ScaleFactor As Single, ByVal ToolTip As String)
        MyBase.new(p)
        pen = New Pen(Brushes.Red)
        _ScaleFactor = ScaleFactor
        Size = New Drawing.Size(My.Resources.blue_MarkerA.Size.Width * ScaleFactor, My.Resources.blue_MarkerA.Size.Height * ScaleFactor)
        Offset = New Drawing.Point(-Size.Width / 2, -Size.Height)
        ToolTipText = ToolTip
        ToolTipMode = WindowsForms.MarkerTooltipMode.OnMouseOver
    End Sub

    Public Overrides Sub OnRender(ByVal g As System.Drawing.Graphics)
        Dim img As Image = My.Resources.blue_MarkerA
        Dim p As Drawing.Point = MyBase.LocalPosition
        g.DrawImage(img, CSng(p.X), CSng(p.Y), img.Width * _ScaleFactor, img.Height * _ScaleFactor)
    End Sub

End Class